// ------------------------------------------------------------------------
// 项目名称：Canroc.Net
// 版权归属：Canroc（https://gitee.com/canroc）
// 
// 许可证信息
// Canroc.Net项目主要遵循 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-APACHE 文件。
// 
// 使用条款：
// 1.使用本项目应遵守相关法律法规和许可证的要求。
// 2.不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动。
// 3.任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Canroc.Net 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// ------------------------------------------------------------------------

using Canroc.Net.Application.SysMailService.Dto;
using Canroc.Net.Event.system.SysMailEvent.Dto;
using Furion.EventBus;

// ReSharper disable once CheckNamespace
namespace Canroc.Net.Application.SysMailService;

/// <summary>
///     系统站内信应用服务
/// </summary>
[ApiDescriptionSettings("System")]
public partial class SysMailAppService(
    SqlSugarRepository<SysMail> mailRep,
    IServiceProvider serviceProvider) : IDynamicApiController, ITransient
{
    /// <summary>
    ///     添加系统站内信
    /// </summary>
    /// <param name="data">表单数据</param>
    /// <returns></returns>
    public async Task<bool> AdditionAsync(MailInput data)
    {
        var entity = data.Adapt<SysMail>();
        return await mailRep.InsertAsync(entity);
    }

    /// <summary>
    ///     编辑系统站内信
    /// </summary>
    /// <param name="data">表单数据</param>
    /// <returns></returns>
    public async Task<bool> EditAsync(MailInput data)
    {
        var entity = await mailRep.GetByIdAsync(data.Id);
        // 更新数据
        data.Adapt(entity);
        return await mailRep.UpdateAsync(entity);
    }

    /// <summary>
    ///     编辑系统站内信状态
    /// </summary>
    /// <param name="data">请求参数</param>
    /// <returns></returns>
    public async Task<bool> PublishAsync(InputModel data)
    {
        // 获取站内信内容
        var mail = await mailRep.GetByIdAsync(data.Id);
        // 更新站内信状态
        var result = await mailRep
            .UpdateAsync(
                m => new SysMail
                {
                    IsPublish = SqlFunc.IIF(m.IsPublish, false, true),
                    PublishTime = SqlFunc.IIF(m.IsPublish, null, (DateTime?)DateTime.Now),
                    CancelTime = SqlFunc.IIF(m.IsPublish, (DateTime?)DateTime.Now, null)
                },
                m => m.Id == mail.Id);

        // 判断站内信是否已发布
        var eventPublisher = serviceProvider.GetRequiredService<IEventPublisher>();
        if (mail.IsPublish)
        {
            // 撤销站内信的发布
            await eventPublisher.PublishAsync(EventTopicConst.SysWithdrawMail,
                new MailWithdrawPayloadInput { MailId = mail.Id });
        }
        else
        {
            // 发布站内信
            await eventPublisher.PublishAsync(EventTopicConst.SysSentMail,
                new MailSentPayloadInput
                {
                    MailId = mail.Id,
                    SendingRange = mail.SendingRange,
                    OrgId = mail.OrgId,
                    RoleIds = mail.RoleIds,
                    UserIds = mail.UserIds
                });
        }

        return result;
    }

    /// <summary>
    ///     删除系统站内信
    /// </summary>
    /// <param name="data">请求参数</param>
    /// <returns></returns>
    public async Task<bool> DelAsync(DeleteInputModel data)
    {
        // 标记站内信删除标识
        _ = await mailRep.UpdateAsync(m => new SysMail { IsDelete = true }, m => data.Ids.Contains(m.Id));
        // 删除站内信和用户关联
        var mailAndUserRep = serviceProvider.GetRequiredService<SqlSugarRepository<RelMailUser>>();
        _ = await mailAndUserRep.DeleteAsync(imu => data.Ids.Contains(imu.MailId));

        return true;
    }

    /// <summary>
    ///     获取系统站内信
    /// </summary>
    /// <param name="id">主键</param>
    /// <returns></returns>
    public async Task<MailOutput?> GetDataAsync(Guid id)
    {
        return await mailRep.GetFirstAsync<MailOutput>(m => m.Id == id);
    }

    /// <summary>
    ///     分页: 系统站内信集合
    /// </summary>
    /// <param name="query">请求参数</param>
    /// <returns></returns>
    public async Task<PageModel<MailPageOutput>> GetPageAsync([FromQuery] MailPageQuery query)
    {
        return await mailRep
            .AsQueryable()
            .WhereIF(query.MailType != null, m => m.MailType == query.MailType)
            .WhereIF(!query.Title.IsNullOrEmpty(), m => m.Title.Contains(query.Title))
            .WhereIF(query.SendingRange != null, m => m.SendingRange == query.SendingRange)
            .WhereIF(query.IsPublish != null, m => m.IsPublish == query.IsPublish)
            .WhereIF(!query.CreateUserName.IsNullOrEmpty(), m => m.CreateUserName.Contains(query.CreateUserName))
            .OrderByPropertyName(query.OrderField, query.IsAscending ? OrderByType.Asc : OrderByType.Desc)
            .Select<MailPageOutput>()
            .ToPageAsync(query.PageIndex, query.PageSize);
    }

    #region 内部函数

    /// <summary>
    ///     获取用户站内信列表
    /// </summary>
    /// <param name="userId">用户Id</param>
    /// <param name="isRead">是否已读</param>
    /// <returns></returns>
    [NonAction]
    public async Task<List<MailShortOutput>> GetMailByUserIdAsync(Guid userId, bool? isRead = null)
    {
        var mailAndUserRep = serviceProvider.GetRequiredService<SqlSugarRepository<RelMailUser>>();
        return await mailAndUserRep
            .AsQueryable()
            .LeftJoin<SysMail>((imu, m) => imu.MailId == m.Id)
            .Where(imu => imu.UserId == userId)
            .WhereIF(isRead != null, imu => imu.IsRead == isRead)
            .Select((imu, m) => new MailShortOutput
            {
                Id = m.Id,
                MailType = m.MailType,
                Title = m.Title,
                IsRead = imu.IsRead,
                CreateTime = m.CreateTime,
                CreateUserName = m.CreateUserName
            })
            .ToListAsync();
    }

    #endregion
}